#include "myserialport.h"
#include <QDebug>

QSerialPort *MySerialPort::open(QObject *parent, QString portname, int baudrate, QString &error)
{
    bool ok;
    QSerialPort *serial = new QSerialPort(portname, parent);
    ok = serial->open(QIODevice::ReadWrite);
    if (!ok) {
        error = "Port open failed";
        goto openPort_fail;
    }
    ok = serial->setBaudRate(baudrate);
    if (!ok) {
        error = "BaudRate set failed";
        goto openPort_fail;
    }
    ok = serial->setDataBits(QSerialPort::Data8);
    if (!ok) {
        error = "DataBits(8) set failed";
        goto openPort_fail;
    }
    ok = serial->setParity(QSerialPort::NoParity);
    if (!ok) {
        error = "Parity(0) set failed";
        goto openPort_fail;
    }
    ok = serial->setStopBits(QSerialPort::OneStop);
    if (!ok) {
        error = "StopBits(1) set failed";
        goto openPort_fail;
    }
    ok = serial->setFlowControl(QSerialPort::NoFlowControl);
    if (!ok) {
        error = "FlowControl set failed";
        goto openPort_fail;
    }
    return serial;

openPort_fail:
    close(serial);
    return nullptr;
}

void MySerialPort::close(QSerialPort *serial)
{
    if (!serial) return;
    if (serial->isOpen()) {
        serial->clear();
        serial->close();
        serial->deleteLater();
    }
    serial = nullptr;
}

void MySerialPort::send(QSerialPort *serial, QByteArray &sendData)
{
    if (!serial || !serial->isOpen()) return;

    int writeBytes = serial->write(sendData);
    serial->flush();

    // qDebug() << __func__ << " write " << writeBytes << "bytes." << sendData.left(11).toHex(' ') << "...";
}

void MySerialPort::sendAndRecv(QSerialPort *serial, QByteArray &sendData, QByteArray &recvData, int &recvLen)
{
    if (!serial || !serial->isOpen()) return;

    send(serial, sendData);

    recv(serial, recvData, recvLen);
}


void MySerialPort::recv(QSerialPort *serial, QByteArray &responseData, int &len)
{
    if (!serial || !serial->isOpen()) return;

    // serial->setReadBufferSize(10240);
    if (!serial->waitForBytesWritten(1000)) {
        qDebug() << "Failed to write command";
        return;
    }

    int round = 2;
read_next:
    int retryCount = 0;
    qDebug() << "round " << round;
    while (!serial->waitForReadyRead(1000)) {
        qDebug() << "Waiting for response timeout, retrying...";
        retryCount++;
        if (retryCount >= 3) { // retry 3 times
            return;
        }
    }

    responseData += serial->readAll();
    while (serial->waitForReadyRead(100)) {
        responseData += serial->readAll();
    }
    len = responseData.length();
    qDebug() << "sync recv " << len << " bytes";
    if (len < 100)
        qDebug() << "sync recv1:" << responseData.toHex(' ').toUpper();

    round--;
    if (round > 0)
        goto read_next;


}
